home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Samples / C++ / DirectInput / DIConfig / usefuldi.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-09-27  |  8.4 KB  |  344 lines

  1. //-----------------------------------------------------------------------------
  2. // File: usefuldi.cpp
  3. //
  4. // Desc: Contains various DInput-specific utility classes and functions
  5. //       to help the UI carry its operations more easily.
  6. //
  7. // Copyright (C) Microsoft Corporation. All Rights Reserved.
  8. //-----------------------------------------------------------------------------
  9.  
  10. #include "common.hpp"
  11.  
  12. // don't want useful.cpp to use precompiled header
  13. #include "useful.cpp"
  14.  
  15.  
  16. BOOL IsObjectOnExcludeList(DWORD dwOfs)
  17. {
  18.     if (dwOfs == DIK_PREVTRACK ||
  19.         dwOfs == DIK_NEXTTRACK ||
  20.         dwOfs == DIK_MUTE ||
  21.         dwOfs == DIK_CALCULATOR ||
  22.         dwOfs == DIK_PLAYPAUSE ||
  23.         dwOfs == DIK_MEDIASTOP ||
  24.         dwOfs == DIK_VOLUMEDOWN ||
  25.         dwOfs == DIK_VOLUMEUP ||
  26.         dwOfs == DIK_WEBHOME ||
  27.         dwOfs == DIK_SLEEP ||
  28.         dwOfs == DIK_WEBSEARCH ||
  29.         dwOfs == DIK_WEBFAVORITES ||
  30.         dwOfs == DIK_WEBREFRESH ||
  31.         dwOfs == DIK_WEBSTOP ||
  32.         dwOfs == DIK_WEBFORWARD ||
  33.         dwOfs == DIK_WEBBACK ||
  34.         dwOfs == DIK_MYCOMPUTER ||
  35.         dwOfs == DIK_MAIL ||
  36.         dwOfs == DIK_MEDIASELECT ||
  37.         dwOfs == DIK_LWIN ||
  38.         dwOfs == DIK_RWIN ||
  39.         dwOfs == DIK_POWER ||
  40.         dwOfs == DIK_WAKE)
  41.         return TRUE;
  42.  
  43.     return FALSE;
  44. }
  45.  
  46. BOOL CALLBACK IncrementValPerObject(LPCDIDEVICEOBJECTINSTANCEW lpddoi, LPVOID pvRef)
  47. {
  48.     if (pvRef != NULL)
  49.         ++(*((int *)pvRef));
  50.     return DIENUM_CONTINUE;
  51. }
  52.  
  53. BOOL CALLBACK KeyboardIncrementValPerObject(LPCDIDEVICEOBJECTINSTANCEW lpddoi, LPVOID pvRef)
  54. {
  55.     if (pvRef != NULL && !IsObjectOnExcludeList(lpddoi->dwOfs))
  56.         ++(*((int *)pvRef));
  57.     return DIENUM_CONTINUE;
  58. }
  59.  
  60. BOOL CALLBACK FillDIDeviceObject(LPCDIDEVICEOBJECTINSTANCEW lpddoi, LPVOID pvRef)
  61. {
  62.     if (pvRef == NULL || lpddoi == NULL)
  63.         return DIENUM_CONTINUE;
  64.  
  65.     DIDEVOBJSTRUCT &os = *((DIDEVOBJSTRUCT *)pvRef);
  66.     assert(os.pdoi != NULL);
  67.     assert(os.n < os.nObjects);
  68.     if (os.pdoi != NULL && os.n < os.nObjects)
  69.         os.pdoi[os.n++] = *lpddoi;
  70.  
  71.     return DIENUM_CONTINUE;
  72. }
  73.  
  74. // This is a special EnumObjects() callback for keyboard type devices.  When we enumerate, dwOfs
  75. // member of lpddoi is meaningless.  We need to take the middle 16 bits of dwType as dwOfs
  76. // (also same as DIK_xxx).
  77. BOOL CALLBACK FillDIKeyboardDeviceObject(LPCDIDEVICEOBJECTINSTANCEW lpddoi, LPVOID pvRef)
  78. {
  79.     if (pvRef == NULL || lpddoi == NULL || IsObjectOnExcludeList(lpddoi->dwOfs))
  80.         return DIENUM_CONTINUE;
  81.  
  82.     DIDEVOBJSTRUCT &os = *((DIDEVOBJSTRUCT *)pvRef);
  83.     assert(os.pdoi != NULL);
  84.     assert(os.n < os.nObjects);
  85.     if (os.pdoi != NULL && os.n < os.nObjects)
  86.     {
  87.         os.pdoi[os.n] = *lpddoi;
  88.         os.pdoi[os.n].dwOfs = os.pdoi[os.n].dwType >> 8;
  89.         wcscpy(os.pdoi[os.n].tszName, lpddoi->tszName);
  90.         ++os.n;
  91.     }
  92.  
  93.     return DIENUM_CONTINUE;
  94. }
  95.  
  96. HRESULT FillDIDeviceObjectStruct(DIDEVOBJSTRUCT &os, LPDIRECTINPUTDEVICE8W pDID)
  97. {
  98.     if (pDID == NULL)
  99.         return E_FAIL;
  100.  
  101.     DIDEVICEINSTANCEW didi;
  102.     didi.dwSize = sizeof(didi);
  103.     pDID->GetDeviceInfo(&didi);
  104.  
  105.     HRESULT hr;
  106.     if (LOBYTE(didi.dwDevType) == DI8DEVTYPE_KEYBOARD)
  107.         hr = pDID->EnumObjects(KeyboardIncrementValPerObject, &os.nObjects,
  108.                 DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV);
  109.     else
  110.         hr = pDID->EnumObjects(IncrementValPerObject, &os.nObjects,
  111.                 DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV);
  112.     if (FAILED(hr))
  113.     {
  114.         os.nObjects = 0;
  115.         return hr;
  116.     }
  117.  
  118.     if (os.nObjects == 0)
  119.         return S_OK;
  120.  
  121.     if (os.pdoi != NULL)
  122.         free(os.pdoi);
  123.     os.pdoi = (DIDEVICEOBJECTINSTANCEW *)malloc(sizeof(DIDEVICEOBJECTINSTANCEW) * os.nObjects);
  124.     if (os.pdoi == NULL)
  125.     {
  126.         os.nObjects = 0;
  127.         return E_FAIL;
  128.     }
  129.  
  130.     // Check if this device is a keyboard. If so, it needs special treatment.
  131.     os.n = 0;
  132.     if ((didi.dwDevType & 0xFF) == DI8DEVTYPE_KEYBOARD)
  133.     {
  134.         hr = pDID->EnumObjects(FillDIKeyboardDeviceObject, &os,
  135.                 DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV);
  136.     } else {
  137.         hr = pDID->EnumObjects(FillDIDeviceObject, &os,
  138.                 DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV);
  139.     }
  140.  
  141.     if (FAILED(hr))
  142.     {
  143.         os.nObjects = 0;
  144.         return hr;
  145.     }
  146.  
  147.     assert(os.nObjects == os.n);
  148.     os.nObjects = os.n;
  149.  
  150.     return S_OK;
  151. }
  152.  
  153. LPTSTR AllocConfigureFlagStr(DWORD dwFlags)
  154. {
  155.     static const AFS_FLAG flag[] = {
  156. #define f(F) { F, _T(#F) }
  157.         f(DICD_EDIT), f(DICD_DEFAULT)
  158. #undef f
  159.     };
  160.     static const int flags = sizeof(flag) / sizeof(AFS_FLAG);
  161.     return AllocFlagStr(dwFlags, flag, flags);
  162. }
  163.  
  164. LPTSTR AllocActionFlagStr(DWORD dwFlags)
  165. {
  166.     static const AFS_FLAG flag[] = {
  167. #define f(F) { F, _T(#F) }
  168.         f(DIA_FORCEFEEDBACK),
  169.         f(DIA_APPMAPPED),
  170.         f(DIA_APPNOMAP),
  171.         f(DIA_NORANGE),
  172. #undef f
  173.     }; static const int flags = sizeof(flag) / sizeof(AFS_FLAG);
  174.     return AllocFlagStr(dwFlags, flag, flags);
  175. }
  176.  
  177. LPTSTR AllocActionHowFlagStr(DWORD dwFlags)
  178. {
  179.     static const AFS_FLAG flag[] = {
  180. #define f(F) { F, _T(#F) }
  181.         f(DIAH_UNMAPPED),
  182.         f(DIAH_USERCONFIG),
  183.         f(DIAH_APPREQUESTED),
  184.         f(DIAH_HWAPP),
  185.         f(DIAH_HWDEFAULT),
  186.         f(DIAH_DEFAULT),
  187.         f(DIAH_ERROR)
  188. #undef f
  189.     }; static const int flags = sizeof(flag) / sizeof(AFS_FLAG);
  190.     return AllocFlagStr(dwFlags, flag, flags);
  191. }
  192.  
  193. void CleanupActionFormatCopy(DIACTIONFORMATW &c)
  194. {
  195.     if (c.rgoAction != NULL)
  196.     {
  197.         for (DWORD i = 0; i < c.dwNumActions; i++)
  198.             if (c.rgoAction[i].lptszActionName != NULL)
  199.                 free((LPTSTR)c.rgoAction[i].lptszActionName);
  200.         free(c.rgoAction);
  201.     }
  202.     c.rgoAction = NULL;
  203. }
  204.  
  205. HRESULT CopyActionFormat(DIACTIONFORMATW &to, const DIACTIONFORMATW &from)
  206. {
  207.     DWORD i;
  208.  
  209.     // copy all simple members
  210.     to = from;
  211.  
  212.     // null copied pointers since we're going to duplicate them (makes sure cleanup works)
  213.     to.rgoAction = NULL;
  214.  
  215.     // handle pointers/arrays/strings
  216.     to.rgoAction = new DIACTIONW [to.dwNumActions];
  217.     if (to.rgoAction == NULL)
  218.         goto fail;
  219.  
  220.     // first null it all 
  221.     memset(to.rgoAction, 0, sizeof(DIACTIONW) * to.dwNumActions);
  222.  
  223.     // now copy...
  224.     for (i = 0; i < to.dwNumActions; i++)
  225.     {
  226.         // copy simple members
  227.         to.rgoAction[i] = from.rgoAction[i];
  228.  
  229.         // handle pointers/arrays/strings
  230.         to.rgoAction[i].lptszActionName = _wcsdup(from.rgoAction[i].lptszActionName);
  231.         if (to.rgoAction[i].lptszActionName == NULL)
  232.             goto fail;
  233.     }
  234.  
  235.     return S_OK;
  236. fail:
  237.     CleanupActionFormatCopy(to);
  238.     return E_OUTOFMEMORY;
  239. }
  240.  
  241. LPDIACTIONFORMATW DupActionFormat(LPCDIACTIONFORMATW lpAcFor)
  242. {
  243.     if (!lpAcFor)
  244.         return NULL;
  245.  
  246.     LPDIACTIONFORMATW pdup = new DIACTIONFORMATW;
  247.     if (!pdup)
  248.         return NULL;
  249.  
  250.     if (FAILED(CopyActionFormat(*pdup, *lpAcFor)))
  251.     {
  252.         delete pdup;
  253.         return NULL;
  254.     }
  255.  
  256.     return pdup;
  257. }
  258.  
  259. void FreeActionFormatDup(LPDIACTIONFORMATW &lpAcFor)
  260. {
  261.     if (!lpAcFor)
  262.         return;
  263.  
  264.     CleanupActionFormatCopy(*lpAcFor);
  265.     delete lpAcFor;
  266.     lpAcFor = NULL;
  267. }
  268.  
  269. void TraceActionFormat(LPTSTR header, const DIACTIONFORMATW &acf)
  270. {
  271. #ifdef CFGUI__TRACE_ACTION_FORMATS
  272.     tracescope(a, header);
  273.     trace(_T("\n"));
  274.  
  275.     traceDWORD(acf.dwSize);
  276.     traceDWORD(acf.dwActionSize);
  277.     traceDWORD(acf.dwDataSize);
  278.     traceDWORD(acf.dwNumActions);
  279.     {tracescope(b, _T("acf.rgoAction Array\n"));
  280.         for (DWORD i = 0; i < acf.dwNumActions; i++)
  281.         {
  282.             const DIACTIONW &a = acf.rgoAction[i];
  283.             static TCHAR buf[MAX_PATH];
  284.             _stprintf(buf, _T("Action %d\n"), i);
  285.             {tracescope(c, buf);
  286.                 traceHEX(a.uAppData);
  287.                 traceDWORD(a.dwSemantic);
  288.                 LPTSTR str = AllocActionFlagStr(a.dwFlags);
  289.                 trace1(_T("a.dwFlags = %s\n"), str);
  290.                 free(str);
  291.                 traceWSTR(a.lptszActionName);
  292.                 traceUINT(a.uResIdString);
  293.                 traceDWORD(a.dwObjID);
  294.                 traceGUID(a.guidInstance);
  295.                 str = AllocActionHowFlagStr(a.dwHow);
  296.                 trace1(_T("a.dwHow = %s\n"), str);
  297.                 free(str);
  298.             }
  299.         }
  300.     }
  301.     traceGUID(acf.guidActionMap);
  302.     traceDWORD(acf.dwGenre);
  303.     traceDWORD(acf.dwBufferSize);
  304.     traceLONG(acf.lAxisMin);
  305.     traceLONG(acf.lAxisMax);
  306.     traceHEX(acf.hInstString);
  307.     traceHEX(acf.dwCRC);
  308.     traceWSTR(acf.tszActionMap);
  309. #endif
  310. }
  311.  
  312. BOOL IsZeroOrInvalidColorSet(const DICOLORSET &cs)
  313. {
  314.     if (cs.dwSize < sizeof(DICOLORSET))
  315.         return TRUE;
  316.  
  317.     const int colors = 8;
  318.     D3DCOLOR color[colors] = {
  319.         cs.cTextFore,
  320.         cs.cTextHighlight,
  321.         cs.cCalloutLine,
  322.         cs.cCalloutHighlight,
  323.         cs.cBorder,
  324.         cs.cControlFill,
  325.         cs.cHighlightFill,
  326.         cs.cAreaFill
  327.     };
  328.  
  329.     for (int i = 0; i < colors; i++)
  330.         if (color[i])
  331.             return FALSE;
  332.  
  333.     return TRUE;
  334. }
  335.  
  336. // D3DCOLOR2COLORREF swaps the blue and red components since GDI and D3D store RGB in the opposite order.
  337. // It also removes the alpha component as the GDI doesn't use that, and including it causes incorrect color.
  338. COLORREF D3DCOLOR2COLORREF(D3DCOLOR c)
  339. {
  340.     LPBYTE pC = (LPBYTE)&c;
  341.  
  342.     return (COLORREF)((DWORD(*pC) << 16) + (DWORD(*(pC+1)) << 8) + DWORD(*(pC+2)));
  343. }
  344.